﻿namespace PowerSong.BibleSupport
    {
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using PowerSong.BibleSupport.FileArchive;
    using PowerSong.Indexer;

    /// <summary>
    /// Represents a Bible indexing manager.
    /// </summary>
    public class BibleIndex
        {

        private Indexer index = null;

        private Searcher searcher = null;

        private ArchiveFile archive = null;

        private string archiveFileName = string.Empty;

        private string indexFileName = string.Empty;

        /// <summary>
        /// Gets the translation of the linked Bible.
        /// </summary>
        /// <value>The translation of the linked Bible.</value>
        public string Translation
            {
            get { return Path.GetFileNameWithoutExtension(archiveFileName); }
            }

        private BibleIndex(string archiveFileName, string indexFileName)
            {
            this.archiveFileName = archiveFileName;
            this.indexFileName = indexFileName;
            this.index = new Indexer();
            this.searcher = new Searcher(index);
            }

        /// <summary>
        /// Loads the given archive file name, which is a file archive storing bible chapters
        /// in a particular format suitable to chapter lookup.
        /// </summary>
        /// <param name="archiveFileName">The name of the bible archive.</param>
        /// <param name="indexFileName">The index file for the bible allowing fast searching.</param>
        /// <returns>Theh bible index, containing methods for dealing with the bible.</returns>
        public static BibleIndex Load(string archiveFileName, string indexFileName)
            {

            var result = new BibleIndex(archiveFileName, indexFileName);
            result.archive = ArchiveFile.Load(archiveFileName);
            result.index = Indexer.LoadIndex(indexFileName);
            result.searcher = new Searcher(result.index);
            return result;

            }

        /// <summary>
        /// Closes the index.
        /// </summary>
        public void Close()
            {
            archive.Close();
            }

        /// <summary>
        /// Finds a bible chapter's contents in the archive based on the given book and chapter.
        /// </summary>
        /// <param name="book">The book.</param>
        /// <param name="chapter">The chapter.</param>
        /// <returns>The contents of the requested bible chapter from the archive.</returns>
        public string FindChapter(BibleSupport.BibleBook book, int chapter)
            {
            return Encoding.ASCII.GetString(archive.GetFile(Convert(book, chapter)));
            }

        /// <summary>
        /// Finds a bible chapter's contents in the archive based on the given file name.
        /// </summary>
        /// <param name="fileName">The name of the bible chapter file in the archive.</param>
        /// <returns>The contents of the requested bible chapter from the archive.</returns>
        public string FindChapter(string fileName)
            {
            return Encoding.ASCII.GetString(archive.GetFile(fileName));
            }

        /// <summary>
        /// Finds a bible chapter's internal filename in the archive based on search keywords.
        /// </summary>
        /// <param name="searchTerms">Search terms used to locate a bible chapter.</param>
        /// <param name="limitResults">The maximum number of results to return.</param>
        /// <returns>The file name requested bible chapter from the archive.</returns>
        public List<string> FindChapters(string searchTerms, int limitResults = 50)
            {

            var fileNames = searcher.Search(searchTerms);
            var result = new List<string>();
            int i = 0;
            foreach (var fileName in fileNames)
                {
                result.Add(fileName);
                i += 1;
                if (i > limitResults) break;
                }
            return result;

            }

        /// <summary>
        /// Determines the file name in the bible archive for the given book and chapter.
        /// </summary>
        /// <param name="book">The bible book.</param>
        /// <param name="chapter">The chapter.</param>
        /// <returns>The filename by which to access the chapter in the bible archive.</returns>
        public static string Convert(BibleSupport.BibleBook book, int chapter)
            {
            return System.Convert.ToInt32(book).ToString() + " " + chapter.ToString() + ".txt";
            }

        /// <summary>
        /// Determines the book and chapter based on the file name of the chapter in the bible archive.
        /// </summary>
        /// <param name="fileName">The name of the file in the archive.</param>
        /// <param name="book">Returns the book.</param>
        /// <param name="chapter">Returns the chapter.</param>
        public static void Convert(string fileName, ref BibleSupport.BibleBook book, ref int chapter)
            {
            var parts = fileName.Split(' ');
            book = (BibleSupport.BibleBook)System.Convert.ToInt32(parts[0]);
            chapter = System.Convert.ToInt32(parts[1]);
            }

        /// <summary>
        /// Retrieves all of the chapter filenames in the archive.
        /// </summary>
        /// <returns>Every book's filename in the archive.</returns>
        public string[] GetAllChapters()
            {
            return archive.GetAllFiles();
            }

        public static void CreateBibleFile(string targetBibleFileName, FileTable allChapters)
            {
            ArchiveFile.Create(targetBibleFileName, allChapters);
            }

        public static void CreateIndexFile(string sourceBibleFileName, string destinationIndexFileName)
            {

            ArchiveFile archive = null;
            try
                {

                // Load the archive
                archive = ArchiveFile.Load(sourceBibleFileName);
                var index = new Indexer();

                // Index chapters
                foreach (var chapter in archive.GetAllFiles())
                    {
                    var data = archive.GetFile(chapter);
                    var contents = Encoding.ASCII.GetString(data);
                    index.AddFileContentsToIndex(chapter, contents);
                    }

                // Save the index
                index.Save(destinationIndexFileName);

                }
            finally
                {
                if (archive != null) archive.Close();
                }

            }

        }

    }
